
#include <stdio.h>
#include <string.h>
#include "wifi.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "lwip/err.h"
#include "lwip/sys.h"

#define ESP_WIFI_SSID "alive_2_4G" /*"alive_2_4G" "FAST_77E2" "Xiaomi 13" "alive"*/
#define ESP_WIFI_PASS "alivegogogo"
#define ESP_MAXIMUM_RETRY 1000

#if CONFIG_ESP_WIFI_AUTH_OPEN
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
#elif CONFIG_ESP_WIFI_AUTH_WEP
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
#endif

/* FreeRTOS 事件组用于在连接时发出信号*/
// EventGroupHandle_t s_wifi_event_group;

/*事件组允许每个事件有多个位，但我们只关心两个事件：
 * 我们使用 IP 连接到了接入点
 * - 我们在最大重试次数后连接失败 */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1

uint8_t esp32_mac[6];
char esp32mac_string[18]; // 6 字节的 MAC 地址，每个字节转换为两位十六进制字符，加上 5 个冒号和一个 null 结尾符

static const char *TAG = "wifi station";

static int s_retry_num = 0; // 重新连接时间

// // 事件处理函数
// void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
// {
//     if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
//     {
//         esp_wifi_connect();
//     }
//     else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
//     {
//         if (s_retry_num < ESP_MAXIMUM_RETRY)
//         {
//             esp_wifi_connect();
//             s_retry_num++;
//             ESP_LOGI(TAG, "retry to connect to the AP");
//         }
//         else
//         {
//             xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
//         }
//         ESP_LOGI(TAG, "connect to the AP fail");
//     }
//     else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
//     {
//         ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
//         ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
//         s_retry_num = 0; // 重连时间清零
//         xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
//     }
// }

// void wifi_init_sta(void)
// {
//     // 初始化nvs
//     esp_err_t ret = nvs_flash_init();
//     if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
//     {
//         ESP_ERROR_CHECK(nvs_flash_erase()); // 删除默认 NVS 分区
//         ret = nvs_flash_init();             // 重新初始化
//     }

//     ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
//     // 创建事件组
//     s_wifi_event_group = xEventGroupCreate();
//     // 初始化底层TCP/IP协议栈
//     ESP_ERROR_CHECK(esp_netif_init());
//     // 创建默认事件循环
//     ESP_ERROR_CHECK(esp_event_loop_create_default());
//     // 创建默认的 wifi sta
//     esp_netif_create_default_wifi_sta();
//     // wifi初始化默认配置
//     wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
//     ESP_ERROR_CHECK(esp_wifi_init(&cfg));
//     // 获取mac地址
//     ESP_ERROR_CHECK(esp_wifi_get_mac(WIFI_IF_STA, esp32_mac));
//     //  printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
//     //        esp32_mac[0], esp32_mac[1], esp32_mac[2],
//     //        esp32_mac[3], esp32_mac[4], esp32_mac[5]);
//     // 将 MAC 地址格式化为字符串
//     sprintf(esp32mac_string, "%02x%02x%02x%02x%02x%02x",
//             esp32_mac[0], esp32_mac[1], esp32_mac[2],
//             esp32_mac[3], esp32_mac[4], esp32_mac[5]);
//     printf("Formatted MAC: %s\n", esp32mac_string);
//     // 向默认循环注册wifi与IP的事件处理程序
//     esp_event_handler_instance_t instance_any_id;
//     esp_event_handler_instance_t instance_got_ip;
//     ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
//                                                         ESP_EVENT_ANY_ID,
//                                                         &wifi_event_handler,
//                                                         NULL,
//                                                         &instance_any_id));
//     ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
//                                                         IP_EVENT_STA_GOT_IP,
//                                                         &wifi_event_handler,
//                                                         NULL,
//                                                         &instance_got_ip));
//     // ESP32 AP 或 STA 的简要配置数据
//     wifi_config_t wifi_config = {
//         .sta = {
//             .ssid = ESP_WIFI_SSID,
//             .password = ESP_WIFI_PASS,
//             /* 如果密码符合 WPA2 标准（密码长度 => 8），自动模式阈值默认重置为 WPA2。
//              * 如果要将设备连接到过时的 WEP/WPA 网络，请将阈值
//              * 设为 WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK，并将密码的长度和格式设为
//              * WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK 标准。
//              */
//             .threshold.authmode = WIFI_AUTH_WPA2_PSK,
//             .sae_pwe_h2e = WPA3_SAE_PWE_BOTH,
//         },
//     };
//     // 设置WiFi运行模式
//     ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
//     // 设置esp32的STA或AP配置
//     ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
//     // 根据当前配置启动 WIFI
//     ESP_ERROR_CHECK(esp_wifi_start());

//     ESP_LOGI(TAG, "wifi_init_sta finished.");

//     /* 等待连接建立（WIFI_CONNECTED_BIT）或连接失败的最大重试次数（WIFI_FAIL_BIT）。
//      * 重试次数（WIFI_FAIL_BIT）。这些位由 event_handler()设置（见上文） */
//     EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
//                                            WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
//                                            pdFALSE,
//                                            pdFALSE,
//                                            portMAX_DELAY);
//     /*xEventGroupWaitBits() 会返回调用返回之前的位，因此我们可以测试哪个事件实际发生了。*/
//     if (bits & WIFI_CONNECTED_BIT)
//     {
//         ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
//                  ESP_WIFI_SSID, ESP_WIFI_PASS);
//     }
//     else if (bits & WIFI_FAIL_BIT)
//     {
//         ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
//                  ESP_WIFI_SSID, ESP_WIFI_PASS);
//     }
//     else
//     {
//         ESP_LOGE(TAG, "UNEXPECTED EVENT"); // 突发事件
//     }
// }

void wifi_scanALLAP(void)
{
    ESP_LOGI("WIFI", "0. 初始化NVS存储");
    // 初始化nvs
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase()); // 删除默认 NVS 分区
        ret = nvs_flash_init();
    }

    ESP_LOGI("WIFI", "1. Wi-Fi 初始化阶段");
    // 初始化底层TCP/IP协议栈
    ESP_ERROR_CHECK(esp_netif_init());
    // 创建默认事件循环
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    // 创建默认的 wifi sta
    esp_netif_create_default_wifi_sta();

    // wifi初始化默认配置
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    // 设置WiFi运行模式
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    // 启动wifi
    ESP_ERROR_CHECK(esp_wifi_start());
    // 配置国家代码
    ESP_ERROR_CHECK(esp_wifi_set_country_code("CN", true));
    // 扫描配置
    wifi_scan_config_t scan_config = {
        .show_hidden = true,
    };
    // 开始扫描
    // bool block设置为true，当扫描到所有的wifi后才会继续执行下面的程序
    // 最高为1.5秒
    esp_wifi_scan_start(&scan_config, true);

    uint16_t ap_num = 0;
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_num));
    ESP_LOGI("WIFI", "AP Count: %d", ap_num);

    uint16_t max_ap = 30; //
    wifi_ap_record_t ap_records[max_ap];
    memset(ap_records, 0, sizeof(ap_records));
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&max_ap, ap_records));

    ESP_LOGI("WIFI", "AP Count: %d", max_ap);

    printf("%30s,%s,%s,%s", "SSID", "频道", "强度", "MAC地址");
    printf("\n");
    if (max_ap == 0)
    {
        printf("No APs found.\n");
    }
    else
    {
        for (int i = 0; i < max_ap; i++)
        {
            printf("%30s  %3d  %3d  %02X-%02X-%02X-%02X-%02X-%02X\n",
                   ap_records[i].ssid, ap_records[i].primary, ap_records[i].rssi,
                   ap_records[i].bssid[0], ap_records[i].bssid[1], ap_records[i].bssid[2],
                   ap_records[i].bssid[3], ap_records[i].bssid[4], ap_records[i].bssid[5]);
        }
    }
}